package com.pi.nbcenter.device.service.huawei;

import java.util.List;

import javax.validation.constraints.NotNull;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.Length;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.pi.base.dto.result.AppResult;
import com.pi.base.dto.result.respcode.error.ErrorServer;
import com.pi.base.enumerate.record.RecordState;
import com.pi.base.exception.ServiceException;
import com.pi.base.util.lang.IntegerUtil;
import com.pi.iot.repository.constants.PiInsEnum;
import com.pi.iot.repository.huawei.bean.IotPartnerConfig;
import com.pi.nbcenter.base.annotation.InsFor;
import com.pi.nbcenter.base.constants.DevState;
import com.pi.nbcenter.base.constants.OnlineStatus;
import com.pi.nbcenter.base.constants.RssiStrength;
import com.pi.nbcenter.base.errorcode.iot.ErrorIOTDev;
import com.pi.nbcenter.device.bean.dto.session.IotDevInstantInfo;
import com.pi.nbcenter.device.entity.auto.IotDeviceInfo;
import com.pi.nbcenter.device.entity.auto.IotDeviceSession;
import com.pi.nbcenter.device.entity.auto.IotPlatformDevEntry;
import com.pi.nbcenter.device.service.comm.BaseServiceProvoder;
import com.pi.nbcenter.device.service.partner.PartnerService;
import com.pi.nbcenter.device.service.pi.internal.IotPlatformDevEntryService;
import com.pi.nbcenter.device.service.pi.internal.PiIotDevService;
import com.pi.nbcenter.device.service.provider.CommonDeviceService;
import com.pi.nbcenter.device.service.provider.FingerService;
import com.pi.nbcenter.device.service.provider.IcCardService;
import com.pi.nbcenter.device.service.provider.LockPasswordService;

@Validated
@Service("HuaWeiIot")
public class HuaWeiDeviceService extends BaseServiceProvoder
  implements CommonDeviceService, IcCardService, FingerService, LockPasswordService{
  private static final Logger logger = LoggerFactory.getLogger(HuaWeiDeviceService.class);
  @Autowired
  private HuaWeiIotService huaWeiPlatformService;
  @Autowired
  private PiIotDevService piIotDevService;
  @Autowired
  private PartnerService partnerService;
  @Autowired
  private IotPlatformDevEntryService iotPlatformDevEntryService;
  
  private static final String DEFAULT_OPEN_LOCK_INS = "ge/ad8XT1takmr4STDqV5A==";
  @Override
  public void addIcCardRemote(
      @NotNull(message = "HUAWEI_DEVICE.IC_CARD_DEVICE_ID_EMPTY") String imei, 
      @NotNull(message = "HUAWEI_DEVICE.IC_CARD_USER_NOT_EMPTY") Long userId, 
      @Length(max=20, message = "HUAWEI_DEVICE.IC_CARD_OVER_MAX") String icCard, 
      @NotNull(message = "HUAWEI_DEVICE.IC_CARD_SOURCE_EMPTY") Long sourceId)
      throws Exception{
    icCardOperateAddEvent(imei, userId, icCard, sourceId);
  }
  @Override
  public void localIcCardRecordRise(
      @NotNull(message = "HUAWEI_DEVICE.IC_CARD_DEVICE_ID_EMPTY") String imei, 
      @NotNull(message = "HUAWEI_DEVICE.IC_CARD_USER_NOT_EMPTY") Long userId, 
      @NotNull(message = "HUAWEI_DEVICE.IC_CARD_SOURCE_EMPTY") Long sourceId) 
          throws Exception {
    icCardOperateAddEvent(imei, userId, null, sourceId);
  }
  

  @Override
  public void deleteUserIcCard(
      @NotNull(message = "HUAWEI_DEVICE.IC_CARD_DEVICE_ID_EMPTY") String imei, 
      @NotNull(message = "HUAWEI_DEVICE.IC_CARD_USER_NOT_EMPTY") Long userId, 
      @Length(max=20, message = "HUAWEI_DEVICE.IC_CARD_OVER_MAX") String icCard,
      @NotNull(message = "HUAWEI_DEVICE.IC_CARD_SOURCE_EMPTY") Long sourceId)
      throws Exception {
    deleteUserIcCardEvent(imei, userId, icCard, sourceId);
  }

  @Override
  public void clearUserIcCard(String imei, Long userId, Long sourceId)
      throws Exception{
    IotPartnerConfig partnerConfig = queryPartnerIotConfig(imei, sourceId);
    huaWeiPlatformService.deleteAllUserIcCard(
        partnerConfig.getIotDevId(), userId, partnerConfig);
  }
  
  @Override
  @Transactional
  public AppResult registerDevice(String imei, Long partnerCode, String nbDevId) throws Exception {
    AppResult result;
    piIotDevService.checkRegisterDevice(imei, partnerCode, nbDevId);
    piIotDevService.checkIotDevId(nbDevId);
    partnerService.queryPartnerInfo(partnerCode);
    String iotDeviceId = null;
    Integer configVersion = null;

    //查询设备是否注册
    //(如果同一个设备平台和合作商都没变, 则不重复注册) 201811--胡工
    IotDeviceInfo info =  piIotDevService.queryDbDeviceInfoByImeiIfExist(imei);
    if(null != info){
      //只有设备未删除的时候判断
      if(info.getState() == RecordState.STATE_NORMAL.getCode().byteValue()){
        if(partnerCode == info.getPartnerCode()){
          logger.info("设备{}的注册信息已存在, 而且是同一个来源, 不重复注册, 来源： {}", imei, partnerCode);
          return AppResult.OK;
        }
        //查询nbDevId是否已存在
        List<IotDeviceInfo> nbDevList = piIotDevService.queryDbDeviceInfoByNbDevIdIfExist(nbDevId);
        if(!CollectionUtils.isEmpty(nbDevList) 
            && (nbDevList.size() > 1 || !nbDevList.get(0).getIotDevImei().equals(imei))) {
          return AppResult.newFailResult(ErrorIOTDev.DEV_ID_EXIST.getKey(),
              ErrorIOTDev.DEV_ID_EXIST.getCode());
        }
        //非同一家厂商则重新查询最新配置
        if(info.getPartnerCode().longValue() != partnerCode){
          configVersion = null;
        }else{
          configVersion = info.getIotProtocolVersion();
        }
      }

      //非同一家厂商则注销平台设备(对于设备回厂又重新卖给其他人的情况)
      piIotDevService.cleanDeviceInfo(info.getIotDevId());
    }else{
      info = new IotDeviceInfo();
      configVersion = null;
    }
    //查询是否有平台配置信息
    IotPartnerConfig config = 
        partnerService.queryPartnerPlatformConfig(partnerCode, configVersion, IotPartnerConfig.class);
    try {
      info.setIotPlatformId(config.getPlatformId());
      iotDeviceId = huaWeiPlatformService.register(imei, config);
      if(StringUtils.isEmpty(iotDeviceId)){
        result = AppResult.newFailResult(
            ErrorIOTDev.REG_DEV_FROM_PLAT_FAILED.getKey(),
            ErrorIOTDev.REG_DEV_FROM_PLAT_FAILED.getCode());
      }else{
        info.setIotDevId(iotDeviceId);
        //注册厂商信息
        boolean succeed = huaWeiPlatformService.updateDevice(iotDeviceId, "", config);
        if(!succeed){
          result = AppResult.newFailResult(ErrorIOTDev.REG_MANUFACTURER_FAILED.getKey(),
              ErrorIOTDev.REG_MANUFACTURER_FAILED.getCode());
        }else{
          //设置证书
          info.setIotDevRegcode(Integer.parseInt(IntegerUtil.generateRandomCode(9))+1000000000);
          huaWeiPlatformService.setCert(iotDeviceId, info.getIotDevRegcode(), "ge/ad8XT1takmr4STDqV5A==", config);
          info.setIotDevImei(imei);
          info.setNbDevId(nbDevId);
  //            info.setOnlineStatus(OnlineStatus.online.value());
          info.setPartnerCode(partnerCode);
          info.setState(DevState.DEV_ADDED.getState());
          info.setIotDevCert("ge/ad8XT1takmr4STDqV5A==");
          info.setIotProtocolVersion(config.getConfigVersion());
          piIotDevService.addDeviceSmart(info);
          
          //注册在线信息
          IotDeviceSession session = new IotDeviceSession();
          session.setIotDevBattery(0);
          session.setIotDevId(iotDeviceId);
          session.setIotDevIp("");
          session.setIotDevPort(0);
          session.setIotDevRssi(RssiStrength.ZERO.value());
          session.setIotDevSeckey(null);
          session.setIotDevState(OnlineStatus.online.value());
  //        在线信息添加开始
          piIotDevService.addDeviceSession(session);
          
          result = AppResult.OK;
        }
      }
    } catch (Exception e) {
      //对于注册成功但是添加失败或者其他异常情况，需要清空设备表数据
      if(null != iotDeviceId){
        try {
          huaWeiPlatformService.deleteDevice(iotDeviceId, config);
        } catch (Exception e1) {
          logger.error("注销平台设备失败",e);
        }
      }
      throw e;
    }
    return result;
  }
  
  @Override
  public AppResult deleteDevice(String imei, Long partnerCode) throws Exception {
    IotDeviceInfo info =  piIotDevService.queryDbDeviceInfoByImei(imei);
    if(!info.getPartnerCode().equals(partnerCode)){
      throw new ServiceException(
          ErrorServer.DEVICE_PLATFORM_NOT_MATCH.getTag(),
          ErrorServer.DEVICE_PLATFORM_NOT_MATCH.getErrorCode());
    }
    //查询是否有平台配置信息
    IotPartnerConfig config = 
        partnerService.queryPartnerPlatformConfig(partnerCode, info.getIotProtocolVersion(), IotPartnerConfig.class);
    huaWeiPlatformService.deleteDevice(info.getIotDevId(), config);
    info.setState(RecordState.STATE_DELETE.getCode().byteValue());
    piIotDevService.updateDeviceInfoById(info);
    return AppResult.OK;
  }

  @Override
  public IotDevInstantInfo queryDeviceStatus(String imei) {
    return piIotDevService.queryDeviceStatus(imei);
  }

  @Override
  public AppResult remoteOpenLock(String imei) throws Exception {
    AppResult result;
    IotDeviceInfo info = piIotDevService.queryDbDeviceInfoByImeiIfExist(imei);
    IotPartnerConfig config = 
        partnerService.queryPartnerPlatformConfig(info.getPartnerCode(), 
            info.getIotProtocolVersion(), IotPartnerConfig.class);
    String response;
    try {
      response = huaWeiPlatformService.openLock(info.getIotDevId(), DEFAULT_OPEN_LOCK_INS, config);
      if(StringUtils.isEmpty(response)){
        result = AppResult.newFailResult("远程开门失败");
      }else{
        JSONObject object = JSON.parseObject(response);
        if(null == object.getInteger("error_code") 
            || object.getInteger("error_code").intValue() == 0){
          result = AppResult.newSuccessResult("远程开门指令发送",null);
        }else{
          result = AppResult.newFailResult(
              null == object.getString("error_desc")?"未知的远程开门错误":object.getString("error_desc"));
        }
      }
    } catch (Exception e) {
      response = null;
      result = AppResult.newFailResult("发送远程开门命令失败");
      logger.error("发送远程开门命令失败",e);
    }
    return result;
  }
  @Override
  public void localFingerEventRise(String imei, Long userId, Long sourceId) throws Exception {
    IotPartnerConfig partnerConfig = queryPartnerIotConfig(imei, sourceId);
    huaWeiPlatformService.addUserFinger(
        partnerConfig.getIotDevId(), userId, partnerConfig);
  }
  @Override
  public void deleteUserFinger(String imei, Long userId, Short fingerId, Long sourceId) throws Exception {
    IotPartnerConfig partnerConfig = queryPartnerIotConfig(imei, sourceId);
    huaWeiPlatformService.delUserFinger(
        partnerConfig.getIotDevId(), userId, fingerId, partnerConfig);
  }
  
  @Override
  public void clearUserFinger(String imei, Long userId, Long sourceId) throws Exception {
    IotPartnerConfig partnerConfig = queryPartnerIotConfig(imei, sourceId);
    huaWeiPlatformService.delAllUserFinger(
        partnerConfig.getIotDevId(), userId, partnerConfig);
  }
  
  @Override
  public void localPasswordEventRise(String imei, Long userId, Long sourceId) throws Exception {
    IotPartnerConfig partnerConfig = queryPartnerIotConfig(imei, sourceId);
    huaWeiPlatformService.addLocalUserPassword(
        partnerConfig.getIotDevId(), userId, partnerConfig);  
  }
  @Override
  public void addPasswordRemote(String imei, Long userId, String password, Long sourceId) throws Exception {
    IotPartnerConfig partnerConfig = queryPartnerIotConfig(imei, sourceId);
    huaWeiPlatformService.addOnlineUserPassword(
        partnerConfig.getIotDevId(), userId, password, partnerConfig);
  }
  @Override
  public void deleteUserPassword(String imei, Long userId, Short password, Long sourceId) throws Exception {
    IotPartnerConfig partnerConfig = queryPartnerIotConfig(imei, sourceId);
    huaWeiPlatformService.delUserPassword(
        partnerConfig.getIotDevId(), userId, password, partnerConfig);
  }
  @Override
  public void clearUserPassword(String imei, Long userId, Long sourceId) throws Exception {
    IotPartnerConfig partnerConfig = queryPartnerIotConfig(imei, sourceId);
    huaWeiPlatformService.delAllUserPassword(
        partnerConfig.getIotDevId(), userId, partnerConfig);  
  }
  @Override
  public void tempPasswordEventRise(String imei, String password, Long sourceId) throws Exception {
    IotPartnerConfig partnerConfig = queryPartnerIotConfig(imei, sourceId);
    huaWeiPlatformService.addTempPassword(
        partnerConfig.getIotDevId(), password, partnerConfig);      
  }
  @InsFor(insEnum = PiInsEnum.LOCK_RESET)
  public void clearLockUserInfo(String imei, Long sourceId) throws Exception{
    IotPartnerConfig partnerConfig = queryPartnerIotConfig(imei, sourceId);
    huaWeiPlatformService.clearUserInfo(partnerConfig.getIotDevId(), partnerConfig);
  }
  private String icCardOperateAddEvent(String imei, Long userId, String icCard, Long sourceId) 
      throws Exception {
    IotPartnerConfig partnerConfig = queryPartnerIotConfig(imei, sourceId);
    //查询ic卡是否已绑定 
    return huaWeiPlatformService.sendUserIcCard(partnerConfig.getIotDevId(), userId, icCard,
        partnerConfig);
  }
  
  private String deleteUserIcCardEvent(String imei, Long userId, String icCard, Long sourceId) 
      throws Exception {
    IotPartnerConfig partnerConfig = queryPartnerIotConfig(imei, sourceId);
    return huaWeiPlatformService.deleteUserIcCard( partnerConfig.getIotDevId(), userId, icCard, 
        partnerConfig);
  }

  private IotPartnerConfig queryPartnerIotConfig(String imei, Long sourceId) throws Exception {
    IotDeviceInfo iotDevice = piIotDevService.queryDbDeviceInfoByImei(imei, sourceId);
    IotPartnerConfig partnerConfig = 
        partnerService.queryPartnerPlatformConfig(sourceId, 
            iotDevice.getIotProtocolVersion(), IotPartnerConfig.class);
    partnerConfig.setIotDevId(iotDevice.getIotDevId());
    return partnerConfig;
  }
  
  
  /**
   * @description 升级现有设备到最新协议, 小批量升级用(会触发流控)
   * @param sourceId 来源
   * @param version 版本号
   * @throws Exception 
   */
  public void upgradeOldversionedDevice(Long sourceId, Integer version, List<String> imeis) throws Exception {
    List<IotDeviceInfo> versionedDeviceList = piIotDevService.queryVersionedIotDevice(sourceId, version, imeis);
    if(null != versionedDeviceList && !versionedDeviceList.isEmpty()){
      StringBuilder deviceIdList = new StringBuilder(versionedDeviceList.size() * 20);
      StringBuilder failDeviceList = new StringBuilder();
      int count =1;
      for(IotDeviceInfo versionedDevice:versionedDeviceList){
        if(count > 10) {
          count = 0;
          Thread.sleep(1000);
        }
        //获取当前设备协议(用于删除)
        IotPartnerConfig config = 
            partnerService.queryPartnerPlatformConfig(
                sourceId, versionedDevice.getIotProtocolVersion(), IotPartnerConfig.class);
        //删除设备
        huaWeiPlatformService.deleteDevice(versionedDevice.getIotDevId(), config);
      //获取最新平台协议
        IotPartnerConfig newConfig = 
            partnerService.queryPartnerPlatformConfig(sourceId, null, IotPartnerConfig.class);
//      设备平台注册 
        String iotDeviceId = huaWeiPlatformService.register(versionedDevice.getIotDevImei(), newConfig);
        if(StringUtils.isNotBlank(iotDeviceId)) {
          //      重新绑定注册信息
          IotDeviceInfo updated = new IotDeviceInfo();
          updated.setId(versionedDevice.getId());
          updated.setIotDevId(iotDeviceId);
          updated.setIotProtocolVersion(newConfig.getConfigVersion());
          updated.setState(RecordState.STATE_NORMAL.getCode().byteValue());
          piIotDevService.updateDeviceInfoById(updated);
          deviceIdList.append(versionedDevice.getId());
          deviceIdList.append(",");
          huaWeiPlatformService.updateDevice(iotDeviceId, "", newConfig);
        }else {
          failDeviceList.append(versionedDevice.getIotDevImei());
          failDeviceList.append(",");
        }
        count ++;
      }
      IotPlatformDevEntry entry = new IotPlatformDevEntry();
      entry.setPlatformDevEntry(deviceIdList.toString());
      entry.setPlatformDevId(0L);
      entry.setUserId(0L);
      entry.setRemark("批量升级设备");
      iotPlatformDevEntryService.insertDevEntry(entry);
      logger.info("升级了{}个设备-{}, 其中成功设备:{}， 失败设备: {}", versionedDeviceList.size(), deviceIdList.toString(), failDeviceList.toString());
    }
  }
}
